import 'package:flutter/material.dart';
import 'package:photo_frame/net/http_manager.dart';
import 'package:photo_frame/net/model/asset_trans_model.dart';
import 'package:photo_frame/router/router_context.dart';
import 'package:photo_frame/utils/a_logger.dart';
import 'package:photo_frame/utils/database_manager.dart';
import 'package:provider/provider.dart';

class AppAssetTransProvider extends ChangeNotifier with WidgetsBindingObserver {
  AppAssetTransProvider() {
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  Map<String, dynamic> transAssetBuffer = {};
  List<String> unUploadAssetIds = [];
  List<AssetTransModel> waitUploadAssetTransModelList = [];
  List<AssetTransModel> allData = [];
  List<String> allAssetIds = [];
  bool uploading = false;

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    // 处理生命周期变化
    switch (state) {
      case AppLifecycleState.inactive:
        print('App is inactive');
        break;
      case AppLifecycleState.paused:
        print('App is paused');
        break;
      case AppLifecycleState.resumed:
        print('App is resumed');
        break;
      case AppLifecycleState.detached:
        print('App is detached');
        break;
      case AppLifecycleState.hidden:
      // TODO: Handle this case.
    }
  }

  updateTransAssetBuffer(String key, dynamic value) {
    transAssetBuffer[key] = value;
  }

  clearTransAssetBuffer({required String key}) {
    transAssetBuffer.remove(key);
  }

  clearAllTransAssetBuffer() {
    transAssetBuffer = {};
  }

  T? transAssetData<T>({required String key}) {
    return transAssetBuffer[key] as T?;
  }

  inpectAssetTransStatus() async {
    List<AssetTransModel> transModelList =
        await DatabaseManager.instance.readAll();
    if (transModelList.isEmpty) return;
    for (var i = 0; i < transModelList.length; i++) {
      AssetTransModel model = transModelList[i];
      if (model.uuid.isNotEmpty && !unUploadAssetIds.contains(model.uuid)) {
        unUploadAssetIds.add(model.uuid);
        if (model.transStatus == 0) {
          waitUploadAssetTransModelList.add(model);
        }
      }
    }
    allData = transModelList;
    allAssetIds = allData.map((data) => data.assetId ?? "").toList();
    startUploadAsset();
    notifyListeners();
  }

  startUploadAsset() async {
    if (uploading) return;
    uploading = true;
    List<String> succeedList = [];

    while (waitUploadAssetTransModelList.isNotEmpty) {
      AssetTransModel model = waitUploadAssetTransModelList.removeAt(0);
      upload(bool compress) async {
        await model.upload(compress, (double progress, String uuid) {
          for (var transModel in allData) {
            if (transModel.uuid == uuid) {
              transModel.progress = progress;
            }
          }
          notifyListeners();
        });
      }

      try {
        await upload(true);
      } catch (e) {
        try {
          //retry
          await upload(false);
          ALogger.e(e);
        } catch (e) {
          ALogger.e(e);
          for (var transModel in allData) {
            if (transModel.uuid == model.uuid) {
              transModel.transStatus = 2;
            }
          }
        }
      }
      await DatabaseManager.instance.update(model);
      if (model.transStatus == 1) {
        for (var transModel in allData) {
          if (transModel.uuid == model.uuid) {
            transModel.transStatus = 1;
          }
        }
        unUploadAssetIds.remove(model.uuid);
        succeedList.add(model.toFrameId ?? "");
      }
      notifyListeners();
    }
    uploading = false;
    ALogger.e("transStatus ${succeedList.length}");
    uploadFinish(succeedList);
  }

  reUpLoadAsset(AssetTransModel assetTransModel) async {
    assetTransModel.transStatus = 0;
    await DatabaseManager.instance.update(assetTransModel);
    notifyListeners();
    waitUploadAssetTransModelList.add(assetTransModel);
    if (!uploading) {
      startUploadAsset();
    }
  }

  deleteTransModel(AssetTransModel model) async {
    if (model.id == null) return;
    await DatabaseManager.instance.delete(model.id!);
    allData.remove(model);
    unUploadAssetIds.remove(model.uuid);
    notifyListeners();
  }

  batchDeleteTransModels(String batchId) async {
    if (batchId.isEmpty) return;
    await DatabaseManager.instance.batchDelete(batchId);
    List<AssetTransModel> buffer = [];
    for (var model in allData) {
      if (model.batchId == batchId) {
        buffer.add(model);
      }
    }
    for (var model in buffer) {
      allData.remove(model);
      unUploadAssetIds.remove(model.uuid);
    }
    notifyListeners();
  }

  deleteAllTransModels() async {
    await DatabaseManager.instance.deleteAll();
    allData.clear();
    allAssetIds.clear();
    unUploadAssetIds.clear();
    waitUploadAssetTransModelList.clear();
    notifyListeners();
  }

  static AppAssetTransProvider provider() {
    return RouterContext.instance.navigatorKey.currentContext!
        .read<AppAssetTransProvider>();
  }
}
